// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;

namespace System
{
#pragma warning disable CS0660, CS0661 // Defining operators, but not overriding Equals/GetHashCode
    public abstract partial class MulticastDelegate : Delegate, ISerializable
    {
        // This constructor is called from the class generated by the
        //    compiler generated code (This must match the constructor
        //    in Delegate
        [RequiresUnreferencedCode("The target method might be removed")]
        protected MulticastDelegate(object target, string method) : base(target, method)
        {
        }

        // This constructor is called from a class to generate a
        // delegate based upon a static method name and the Type object
        // for the class defining the method.
        protected MulticastDelegate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.AllMethods)] Type target, string method) : base(target, method)
        {
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool operator ==(MulticastDelegate? d1, MulticastDelegate? d2)
        {
            // Test d2 first to allow branch elimination when inlined for null checks (== null)
            // so it can become a simple test
            if (d2 is null)
            {
                return d1 is null;
            }

            return ReferenceEquals(d2, d1) || d2.Equals(d1);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool operator !=(MulticastDelegate? d1, MulticastDelegate? d2)
        {
            // Can't call the == operator as it will call object==

            // Test d2 first to allow branch elimination when inlined for not null checks (!= null)
            // so it can become a simple test
            if (d2 is null)
            {
                return d1 is not null;
            }

            return !ReferenceEquals(d2, d1) && !d2.Equals(d1);
        }
    }
#pragma warning restore CS0660, CS0661
}
